/**
  ******************************************************************************
    File Name          : DAC.c
    Description        : This file provides code for the configuration
                         of the DAC instances.
  ******************************************************************************
    @attention

    <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
    All rights reserved.</center></h2>

    This software component is licensed by ST under BSD 3-Clause license,
    the "License"; You may not use this file except in compliance with the
    License. You may obtain a copy of the License at:
                           opensource.org/licenses/BSD-3-Clause

  ******************************************************************************
*/

/* Includes ------------------------------------------------------------------*/
#include "dac.h"

/* USER CODE BEGIN 0 */

extern TIM_HandleTypeDef htim6;

/* USER CODE END 0 */

DAC_HandleTypeDef hdac;
DMA_HandleTypeDef hdma_dac_ch1;

/* DAC init function */
void MX_DAC_Init(void)
{
    DAC_ChannelConfTypeDef sConfig = {0};
    /** DAC Initialization
    */
    hdac.Instance = DAC;
    if (HAL_DAC_Init(&hdac) != HAL_OK)
    {
        Error_Handler();
    }
    /** DAC channel OUT1 config
    */
    sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
    sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
    if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK)
    {
        Error_Handler();
    }
}

void HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(dacHandle->Instance == DAC)
    {
        /* USER CODE BEGIN DAC_MspInit 0 */
        /* USER CODE END DAC_MspInit 0 */
        /* DAC clock enable */
        __HAL_RCC_DAC_CLK_ENABLE();
        __HAL_RCC_GPIOA_CLK_ENABLE();
        /** DAC GPIO Configuration
            PA4     ------> DAC_OUT1
        */
        GPIO_InitStruct.Pin = GPIO_PIN_4;
        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        /* DAC DMA Init */
        /* DAC_CH1 Init */
        hdma_dac_ch1.Instance = DMA2_Channel3;
        hdma_dac_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH;
        hdma_dac_ch1.Init.PeriphInc = DMA_PINC_DISABLE;
        hdma_dac_ch1.Init.MemInc = DMA_MINC_ENABLE;
        hdma_dac_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        hdma_dac_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        hdma_dac_ch1.Init.Mode = DMA_NORMAL;
        hdma_dac_ch1.Init.Priority = DMA_PRIORITY_HIGH;
        if (HAL_DMA_Init(&hdma_dac_ch1) != HAL_OK)
        {
            Error_Handler();
        }
        __HAL_LINKDMA(dacHandle, DMA_Handle1, hdma_dac_ch1);
        /* USER CODE BEGIN DAC_MspInit 1 */
        /* USER CODE END DAC_MspInit 1 */
    }
}

void HAL_DAC_MspDeInit(DAC_HandleTypeDef* dacHandle)
{
    if(dacHandle->Instance == DAC)
    {
        /* USER CODE BEGIN DAC_MspDeInit 0 */
        /* USER CODE END DAC_MspDeInit 0 */
        /* Peripheral clock disable */
        __HAL_RCC_DAC_CLK_DISABLE();
        /** DAC GPIO Configuration
            PA4     ------> DAC_OUT1
        */
        HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4);
        /* DAC DMA DeInit */
        HAL_DMA_DeInit(dacHandle->DMA_Handle1);
        /* USER CODE BEGIN DAC_MspDeInit 1 */
        /* USER CODE END DAC_MspDeInit 1 */
    }
}

/* USER CODE BEGIN 1 */
uint8_t* data;
uint32_t len;

// This function will be called when DMA transfer complete
//
void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef* hdac)
{
    if(len > 0xFFFF)
    {
        HAL_DAC_Start_DMA(hdac, DAC_CHANNEL_1, (uint32_t*)data, 0xFFFF, DAC_ALIGN_8B_R);
        HAL_TIM_Base_Start(&htim6);
        data += 0xFFFF;
        len -= 0xFFFF;
    }
    else if(len > 0)
    {
        HAL_DAC_Start_DMA(hdac, DAC_CHANNEL_1, (uint32_t*)data, len, DAC_ALIGN_8B_R);
        HAL_TIM_Base_Start(&htim6);
        len = 0;
    }
    else
    {
        StopMusic();
    }
}

void PlayMusic(uint8_t* waveData, uint32_t waveLen)
{
    // load raw sample data
    data = waveData;
    len = waveLen;
    // start DMA
    HAL_DAC_ConvCpltCallbackCh1(&hdac);
}

void StopMusic(void)
{
    HAL_TIM_Base_Stop(&htim6);
    HAL_DAC_Stop_DMA(&hdac, DAC_CHANNEL_1);
    len = 0;
}

/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
